package com.xushu.circulardependencies.One;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/***
 * @Author 徐庶
 * @Slogan 致敬大师，致敬未来的你
 */
public class XuShuApplicationContext  {


    private Map<String, BeanDefinition> beanDefinitionMap = new LinkedHashMap<>(256);

	// 单例池  一级缓存
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	// 二级缓存  ：临时bean对象  提升性能
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(256);
	// 三级缓存 AOP : 函数接口-->  提升扩展性     保证规范
	private final Map<String, ObjectFactory> factoriesSingletonObjects = new ConcurrentHashMap<>(256);


	public XuShuApplicationContext() throws Exception {

        // 加载ioc容器
        refresh();
    }

	// ioc容器加载
    private void refresh() throws Exception {

        // todo 解析配置
		// 注册BeanDefinition
        loadBeanDefinitions();

		// 创建所有的单例bean
		finishBeanFactoryInitialization();
    }

	private void finishBeanFactoryInitialization() throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
		// todo.  bean加载
		for (String beanName : beanDefinitionMap.keySet()) {
			getBean(beanName);
		}

	}

	// 创建bean
	public Object getBean(String beanName) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

		// 1. 获取
		Object bean = getSingleton(beanName);

		if (bean != null) {
			return bean;
		}

		synchronized (singletonObjects) {

			// 第二重检查
			if(singletonObjects.containsKey(beanName)){
				return singletonObjects.get(beanName);
			}



			// 实例化
			RootBeanDefinition rootBeanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
			Class<?> beanClass = rootBeanDefinition.getBeanClass();
			Object beanInstan = beanClass.getConstructor().newInstance();


			// 只有在循环依赖  中实现   创建动态代理
			factoriesSingletonObjects.put(beanName,() -> {
				return new JdkProxyBeanPostProcessor().getEarlyBeanReference(beanInstan, beanName);
			});


			// 属性注入
			Field[] declaredFields = beanClass.getDeclaredFields();
			for (Field declaredField : declaredFields) {
				// 说明属性有@Autowired
				if (declaredField.getAnnotation(Autowired.class) != null) {
					// bytype  byname
					String name = declaredField.getName();
					Object dependBean = getBean(name);

					declaredField.setAccessible(true);
					declaredField.set(beanInstan, dependBean);

				}
			}

			// 初始化--AOP


			// put 单例池
			singletonObjects.put(beanName, beanInstan);
			earlySingletonObjects.remove(beanName);

			return beanInstan;

		}
	}

	// 获取bean
	private Object getSingleton(String beanName) {

		if (singletonObjects.containsKey(beanName)) {
			return singletonObjects.get(beanName);
		}


		synchronized (singletonObjects) {
			if (earlySingletonObjects.containsKey(beanName)) {


				return earlySingletonObjects.get(beanName);
			}

			// 出口  三级缓存
			if (factoriesSingletonObjects.containsKey(beanName)) {
				ObjectFactory objectFactory = factoriesSingletonObjects.get(beanName);

				Object beanAop = objectFactory.getObject();

				earlySingletonObjects.put(beanName, beanAop);

				return beanAop;

			}
			return null;
		}
	}


	/**
	 *
	 *  根据配置信息创建BeanDefinition  底层是通过解析配置类注册beandefinition
	 */
	private void loadBeanDefinitions() {
		// 创建A    BeanDefinition
		RootBeanDefinition aBeanDefinition = new RootBeanDefinition(AService.class);
		// 创建B    BeanDefinition
		RootBeanDefinition bBeanDefinition = new RootBeanDefinition(BService.class);
		beanDefinitionMap.put("aService", aBeanDefinition);
		beanDefinitionMap.put("bService", bBeanDefinition);
	}


}
